package com.xnew.common.utils;


import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by tinx on 2018-7-20.
 */
public final class DateUtil {
    public static final String DATE_PATTERN = "yyyy-MM-dd";
    public static final String DATE_INTEGER_PATTERN = "yyyyMMdd";
    public static final String TIMESTAMP_PATTERN = "yyyy-MM-dd HH:mm:ss";
    public static final String TIME_PATTERN = "HH:mm:ss";
    public static final String TIME_PATTERN_HH_mm = "HH:mm";
    private static Logger logger = LoggerFactory.getLogger(DateUtil.class);

    private DateUtil() {
    }

    public static String parseDate(long timestamp,String format){
        Date date = new Date(timestamp);
        return format(date,format);
    }

    public static Date getBeginningOfDay(Date date) {
        date = DateUtils.setHours(date, 0);
        date = DateUtils.setMinutes(date, 0);
        date = DateUtils.setSeconds(date, 0);
        date = DateUtils.setMilliseconds(date, 0);
        return date;
    }

    public static Date getEndingOfDay(Date date) {
        date = DateUtils.setHours(date, 23);
        date = DateUtils.setMinutes(date, 59);
        date = DateUtils.setSeconds(date, 59);
        date = DateUtils.setMilliseconds(date, 999);
        return date;
    }

    /**
     *  根据传入时间 获取上周一时间
     * @param time
     * @return
     */
    public static String getLastWeekMonday(String time) {
        SimpleDateFormat foramt = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = foramt.parse(time);

        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar  cal = Calendar.getInstance();
        cal.setTime(date);
        if (1 == cal.get(Calendar.DAY_OF_WEEK)) {//判断当前日期是否为周末，因为周末是本周第一天，如果不向后推迟一天的到的将是下周一的零点，而不是本周周一零点
            cal.add(Calendar.DATE, -1);
        }
        cal.add(Calendar.DAY_OF_MONTH, -7);//时间减去7天
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);//Calendar.MONDAY 这个是周一的意思      想获取周几就更换这个

        return foramt.format(cal.getTime()) + " 00:00:00";
    }

    /**
     * 根据传入时间 获取上周周天时间
     * @param time
     * @return
     */
    public static String getLastWeekSunday(String time) {
        SimpleDateFormat foramt = new SimpleDateFormat("yyyy-MM-dd");
        Date date = null;
        try {
            date = foramt.parse(time);

        } catch (ParseException e) {
            e.printStackTrace();
        }
        Calendar  cal = Calendar.getInstance();
        cal.setTime(date);

        if (1 == cal.get(Calendar.DAY_OF_WEEK)) {//判断当前日期是否为周末，因为周末是本周第一天，如果不向后推迟一天的到的将是下周一的零点，而不是本周周一零点
            cal.add(Calendar.DATE, -1);
        }
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);//Calendar.SUNDAY 周天想获取周几就更换这个
        return foramt.format(cal.getTime()) + " 23:59:59";
    }

    public static Date getLastWeekMonday(Date date){
        if(date==null){
            date = new Date();
        }
        Calendar  cal = Calendar.getInstance();
        cal.setTime(date);
        if (1 == cal.get(Calendar.DAY_OF_WEEK)) {//判断当前日期是否为周末，因为周末是本周第一天，如果不向后推迟一天的到的将是下周一的零点，而不是本周周一零点
            cal.add(Calendar.DATE, -1);
        }
        cal.add(Calendar.DAY_OF_MONTH, -7);//时间减去7天
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);//Calendar.MONDAY 这个是周一的意思      想获取周几就更换这个
        cal.set(Calendar.HOUR, -12);
        cal.set(Calendar.MINUTE, 00);
        cal.set(Calendar.SECOND, 00);
        return cal.getTime();
    }

    public static Date getLastWeekSunday(Date date){
        if(date==null){
            date = new Date();
        }
        Calendar  cal = Calendar.getInstance();
        cal.setTime(date);
        if (1 == cal.get(Calendar.DAY_OF_WEEK)) {//判断当前日期是否为周末，因为周末是本周第一天，如果不向后推迟一天的到的将是下周一的零点，而不是本周周一零点
            cal.add(Calendar.DATE, -1);
        }
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);//Calendar.SUNDAY 周天想获取周几就更换这个
//        cal.set(Calendar.HOUR, 23);
//        cal.set(Calendar.MINUTE, 59);
//        cal.set(Calendar.SECOND, 59);
        return getEndingOfDay(cal.getTime());
    }

    public static Date getBeginningOfWeek(Date date) {
        if(date==null){
            date = new Date();
        }
        Calendar cal=Calendar.getInstance();
        cal.setTime(date);
        int dayOfWeek = cal.get(Calendar.DAY_OF_WEEK);
        cal.add(Calendar.DAY_OF_WEEK, 0);
        cal.set(Calendar.DAY_OF_WEEK, 2);
//        cal.set(Calendar.HOUR, 00);
//        cal.set(Calendar.MINUTE, 00);
//        cal.set(Calendar.SECOND, 00);
//        return cal.getTime();
        return getBeginningOfDay(cal.getTime());
    }

    public static Date getEndingOfWeek(Date date) {
        if(date==null){
            date = new Date();
        }
        Calendar cal=Calendar.getInstance();
        cal.setTime(date);
        cal.set(Calendar.DAY_OF_WEEK, cal.getActualMaximum(Calendar.DAY_OF_WEEK));
        cal.add(Calendar.DAY_OF_WEEK, 1);
//        cal.set(Calendar.HOUR, 23);
//        cal.set(Calendar.MINUTE, 59);
//        cal.set(Calendar.SECOND, 59);
//        return cal.getTime();
        return getEndingOfDay(cal.getTime());
    }

    public static Date getNextWeekMonday(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginningOfWeek(date));
        cal.add(Calendar.DATE, 7);
        cal.set(Calendar.HOUR, 00);
        cal.set(Calendar.MINUTE, 00);
        cal.set(Calendar.SECOND, 00);
        return cal.getTime();
    }

    public static Date getNextWeekSunday(Date date){
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginningOfWeek(date));
        cal.add(Calendar.DATE, 13);
        cal.set(Calendar.HOUR, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        return cal.getTime();
    }

    public static Date getBeginningOfMonth(Date date) {
        date = DateUtils.setDays(date, 1);
        return getBeginningOfDay(date);
    }

    /**
     * @Description 根据当前日期获取本季度第一天
     * @param
     * @Throws
     * @Return java.util.Date
     * @Date 2021-08-31 15:37:11
     * @Author WangKun
     **/
    public static Date getBeginningOfQuarter(Date date) {
        if(date==null){
            date = new Date();
        }
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int currentMonth = c.get(Calendar.MONTH) + 1;
        SimpleDateFormat longSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        SimpleDateFormat shortSdf = new SimpleDateFormat("yyyy-MM-dd");
        Date now = null;
        try {
            if (currentMonth <= 3)
                c.set(Calendar.MONTH, 0);
            else if (currentMonth <= 6)
                c.set(Calendar.MONTH, 3);
            else if (currentMonth <= 9)
                c.set(Calendar.MONTH, 6);
            else if (currentMonth <= 12)
                c.set(Calendar.MONTH, 9);
            c.set(Calendar.DATE, 1);
            now = longSdf.parse(shortSdf.format(c.getTime()) + " 00:00:00");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return now;
    }

    /**
     * @Description 根据当前日期获取本季度最后一天
     * @Return java.util.Date
     * @Date 2021-08-31 15:30:23
     **/
    public static Date getEndingOfQuarter(Date date) {
        if(date == null){
            date = new Date();
        }
        Calendar cal = Calendar.getInstance();
        cal.setTime(getBeginningOfQuarter(date));
        cal.add(Calendar.MONTH, 2);
        cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    public static Date getEndingOfMonth(Date date) {
        date = getBeginningOfMonth(date);
        date = DateUtils.addMonths(date, 1);
        date = DateUtils.addDays(date, -1);
        return getEndingOfDay(date);
    }

    public static Date getEndingOfYear(Date date) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        int maxDay = c.getActualMaximum(Calendar.DAY_OF_YEAR);
        int today = c.get(Calendar.DAY_OF_YEAR);
        return new Date((maxDay - today) * 24 * 60 * 60 * 1000);
    }

    public static boolean isBetween(Date source, Date date1, Date date2) {
        if (source == null && date1 == null && date2 == null) {
            return true;
        }

        if (source == null || date1 == null || date2 == null) {
            return false;
        }
        return source.compareTo(date1) >= 0 && source.compareTo(date2) <= 0;
    }

    public static Date addMonth(Date date, int amount) {
        return DateUtils.addMonths(date, amount);
    }

    public static Date addDay(Date date, int amount) {
        return DateUtils.addDays(date, amount);
    }

    /**
     * 获取当前时间
     * <p>
     * createTime 2017-8-23 15:53
     *
     * @return Date
     * @author tinx
     */
    public static Date getCurrentDate() {
        return getCurrentDate(true);
    }

    /**
     * 
     * 创建时间 2018-8-9 14:09
     * @author tinx
     * @param needTime 是否需要时间部分
     * @return
     */
    public static Date getCurrentDate(boolean needTime) {
        Calendar now = Calendar.getInstance();
        if (needTime) {
            return now.getTime();
        } else {
            now.set(Calendar.HOUR_OF_DAY, 0);
            now.set(Calendar.MINUTE, 0);
            now.set(Calendar.SECOND, 0);
            now.set(Calendar.MILLISECOND, 0);
            return now.getTime();
        }
    }

    /**
     * 字符串转日期
     * 创建时间 2017-8-25 18:14
     *
     * @param dateStr
     * @param pattern
     * @return
     */
    public static Date parseDate(String dateStr, String pattern) {
        try {
            return DateUtils.parseDate(dateStr, pattern);
        } catch (ParseException e) {
            throw new IllegalArgumentException("dateStr is not fitted for pattern");
        }
    }

    public static Date parseDate(String dateStr) {
        SimpleDateFormat format = null;
        if (StringUtils.isBlank(dateStr))
            return null;
        String _dateStr = dateStr.trim();
        try {
            if (_dateStr.matches("\\d{1,2}[A-Z]{3}")) {
                _dateStr = _dateStr + (Calendar.getInstance().get(Calendar.YEAR) - 2000);
            }
            // 01OCT12
            if (_dateStr.matches("\\d{1,2}[A-Z]{3}\\d{2}")) {
                format = new SimpleDateFormat("ddMMMyy", Locale.ENGLISH);
            } else if (_dateStr.matches("\\d{1,2}[A-Z]{3}\\d{4}.*")) {// 01OCT2012
                // ,01OCT2012
                // 1224,01OCT2012
                // 12:24
                _dateStr = _dateStr.replaceAll("[^0-9A-Z]", "").concat("000000").substring(0, 15);
                format = new SimpleDateFormat("ddMMMyyyyHHmmss", Locale.ENGLISH);
            } else {
                StringBuffer sb = new StringBuffer(_dateStr);
                String[] tempArr = _dateStr.split("\\s+");
                tempArr = tempArr[0].split("-|\\/");
                if (tempArr.length == 3) {
                    if (tempArr[1].length() == 1) {
                        sb.insert(5, "0");
                    }
                    if (tempArr[2].length() == 1) {
                        sb.insert(8, "0");
                    }
                }
                _dateStr = sb.append("000000").toString().replaceAll("[^0-9]", "").substring(0, 14);
                if (_dateStr.matches("\\d{14}")) {
                    format = new SimpleDateFormat("yyyyMMddHHmmss");
                }
            }

            if (format == null) {
                return null;
            }
            Date date = format.parse(_dateStr);
            return date;
        } catch (Exception e) {
            throw new RuntimeException("无法解析日期字符[" + dateStr + "]");
        }
    }

    public static String format(Date date, String... patterns) {
        if (date == null)
            return "";
        String pattern = TIMESTAMP_PATTERN;
        if (patterns != null && patterns.length > 0 && !StringUtils.isBlank(patterns[0])) {
            pattern = patterns[0];
        }
        return DateFormatUtils.format(date, pattern);
    }

    /**
     * 把日期部分格式化成整型
     *
     * @param date 日期
     * @return Integer
     */
    public static Integer formatDate2Integer(Date date) {
        String dateString = format(date, DATE_INTEGER_PATTERN);
        Integer result = Integer.parseInt(dateString);
        return result;
    }

    public static Date getSaasCreateDate() {
        SimpleDateFormat beferDateFormat = new SimpleDateFormat(DATE_PATTERN);
        Date saasDate = null;
        try {
            saasDate = beferDateFormat.parse("2017-09-13");
        } catch (ParseException e) {
            logger.error("", e);
        }
        return saasDate;
    }

    public static Date getDate(String type, String strDate) {
        SimpleDateFormat beferDateFormat = new SimpleDateFormat(type);
        Date date = null;
        try {
            date = beferDateFormat.parse(strDate);
        } catch (ParseException e) {
            logger.error("", e);
        }
        return date;
    }

    public static Map<String, Date> convertMonthByDate(Date date) {
        Map<String, Date> map = new HashMap<String, Date>();
        // 指定日期月第一天
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.HOUR, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.DATE, 1);
        Date theDate = calendar.getTime();
        // 指定日期月最后一天
        calendar.add(Calendar.MONTH, 1); // 加一个月
        calendar.set(Calendar.DATE, 1); // 设置为该月第一天
        calendar.add(Calendar.DATE, -1); // 再减一天即为上个月最后一天
        calendar.set(Calendar.HOUR, 23);
        calendar.set(Calendar.MINUTE, 59);
        calendar.set(Calendar.SECOND, 59);
        map.put("first", theDate);
        map.put("last", calendar.getTime());
        return map;
    }

    public static List<String> getMonthBetween(String minDate, String maxDate) {
        ArrayList<String> result = new ArrayList<String>();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM");//格式化为年月

        Calendar min = Calendar.getInstance();
        Calendar max = Calendar.getInstance();

        try {
            min.setTime(sdf.parse(minDate));
            min.set(min.get(Calendar.YEAR), min.get(Calendar.MONTH), 1);

            max.setTime(sdf.parse(maxDate));
            max.set(max.get(Calendar.YEAR), max.get(Calendar.MONTH), 2);

        } catch (ParseException e) {
            logger.error(e.getMessage(), e);
        }
        Calendar curr = min;
        while (curr.before(max)) {
            result.add(sdf.format(curr.getTime()));
            curr.add(Calendar.MONTH, 1);
        }

        return result;
    }

    public static List<String> betweenList(Date date){
        Date start = DateUtil.getBeginningOfMonth(date);
        Calendar c = Calendar.getInstance();
        c.setTime(start);
        int startDay=c.get(Calendar.DATE);
        Date end = DateUtil.getEndingOfMonth(date);
        c.setTime(end);
        int endDay=c.get(Calendar.DATE);
        int month = c.get(Calendar.MONTH)+1;
        String m = ""+month;
        if(m.length()==1){
            m = "0"+m;
        }
        List<String> list = new ArrayList<>();
        for(int i = startDay;i< endDay;i++){
            String d = ""+i;
            if(d.length()==1){
                d = "0"+d;
            }
            list.add(c.get(Calendar.YEAR)+"-"+m+"-"+d);
        }
        list.add(format(end,"yyyy-MM-dd"));
        return list;
    }

    /**
     * 获得指定日期的前一天
     * @param specifiedDay
     * @return
     * @throws Exception
     */
    public static String getSpecifiedDayBefore(String specifiedDay){
//SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        Date date=null;
        try {
            date = new SimpleDateFormat("yy-MM-dd").parse(specifiedDay);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        c.setTime(date);
        int day=c.get(Calendar.DATE);
        c.set(Calendar.DATE,day-1);

        String dayBefore=new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
        return dayBefore;
    }

    public static Date getSpecifiedDayBefore(Date specifiedDay){
//SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        Calendar c = Calendar.getInstance();
        c.setTime(specifiedDay);
        int day=c.get(Calendar.DATE);
        c.set(Calendar.DATE,day-1);
        return c.getTime();
    }
    /**
     * 获得指定日期的后一天
     * @param specifiedDay
     * @return
     */
    public static String getSpecifiedDayAfter(String specifiedDay){
        Calendar c = Calendar.getInstance();
        Date date=null;
        try {
            date = new SimpleDateFormat("yy-MM-dd").parse(specifiedDay);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        c.setTime(date);
        int day=c.get(Calendar.DATE);
        c.set(Calendar.DATE,day+1);

        String dayAfter=new SimpleDateFormat("yyyy-MM-dd").format(c.getTime());
        return dayAfter;
    }

    public static Date getSpecifiedDayAfter(Date specifiedDay){
        Calendar c = Calendar.getInstance();
//        Date date=null;
//        try {
//            date = new SimpleDateFormat("yy-MM-dd").parse(specifiedDay);
//        } catch (ParseException e) {
//            e.printStackTrace();
//        }
        c.setTime(specifiedDay);
        int day=c.get(Calendar.DATE);
        c.set(Calendar.DATE,day+1);

        return c.getTime();
    }

    public static long parseTimestamp(String dateStr){
        Date date = parseDate(dateStr);
        return date.getTime();
    }

    public static void main(String[] args){
        String strDate = "2022-02-01";

        Date date = new Date();
        System.out.println("上周："+format(getLastWeekMonday(date),TIMESTAMP_PATTERN)+" "+format(getLastWeekSunday(date),TIMESTAMP_PATTERN));
        System.out.println("本周："+format(getBeginningOfWeek(date),TIMESTAMP_PATTERN)+" "+format(getEndingOfWeek(date),TIMESTAMP_PATTERN));
        System.out.println("下周："+format(getNextWeekMonday(date),TIMESTAMP_PATTERN)+" "+format(getNextWeekSunday(date),TIMESTAMP_PATTERN));
        System.out.println("本月："+format(getBeginningOfMonth(date),TIMESTAMP_PATTERN)+" "+format(getEndingOfMonth(date),TIMESTAMP_PATTERN));
        System.out.println("本季："+format(getBeginningOfQuarter(date),TIMESTAMP_PATTERN)+" "+format(getEndingOfQuarter(date),TIMESTAMP_PATTERN));
//        String str = "2019-02-01";
//        Date date = parseDate(str);
//        Date first = getBeginningOfMonth(date);
//        Date end = getEndingOfMonth(date);
//        System.out.println(format(first,"yyyy-MM-dd"));
//        System.out.println(format(end,"yyyy-MM-dd"));
    }
}
